import * as Common from './common';
import Bridge from './bridge';

class WebSocket2 {
    constructor(props) {
        this.props = props;
        this.id = Common.createGuid();

        this.receiveFunctions = {};
        this.receiveFunctions2 = props.receiveFunctions || {};

        this.initSocket();
    }

    initSocket() {
        const { serviceUrl, roomId } = this.props;
        if (!serviceUrl || !roomId) return;

        const url = `${serviceUrl}/ws/chat/${roomId}?id=${this.id}`;
        const socket = new WebSocket(url);
        const $this = this;

        socket.onopen = function (event) {
            console.log(Common.getCurrentDate() + ' Connection opened');
            $this.isOpen = true;
        };

        socket.onmessage = function (event) {
            console.log('Message from server ', event.data);
            $this.receiveMessage(event.data);
        };

        socket.onerror = function (event) {
            $this.isOpen = false;
            console.error('WebSocket error observed:', event);
        };

        socket.onclose = function (event) {
            $this.isOpen = false;
            console.log(Common.getCurrentDate() + ' Connection closed');
            setTimeout(() => $this.initSocket(), 100);
        };
        this.socket = socket;

        // if (this.intervalId > 0) clearInterval(this.intervalId);

        // this.intervalId = setInterval(() => {
        //     try {
        //         if (this.isOpen) this.socket.send('ping');
        //         else clearInterval(this.intervalId);
        //     }
        //     catch (err) {
        //         console.error(err);
        //         clearInterval(this.intervalId);
        //     }
        // }, 50000);
    }

    send(type, data) {
        if (!this.socket) return;
        if (!this.isOpen) {
            console.error('WebSocket connection is not opened');
            return;
        }
        this.socket.send(JSON.stringify({ id: this.id, type, data }));
    }

    setReceiveFunction(type, fn) {
        this.receiveFunctions[type] = fn;
    }

    receiveMessage(message) {
        if (!message || message === 'ping') {
            this.socket.send('pong');
            return;
        }

        if (message === 'pong') return;

        const msg = JSON.parse(message);
        if (!msg || !msg.id || !msg.type) return;

        if (msg.id === this.id && msg.type !== 'add' && msg.type !== 'remove') return;

        if (msg.data) msg.data.webSocketId = msg.id;
        let fn = this.receiveFunctions[msg.type];
        if (!fn) fn = this.receiveFunctions2[msg.type];
        fn && fn(msg.data || msg);
    }
}

WebSocket2.instances = {};
WebSocket2.getWebSocket = (roomId, receiveFunctions) => {
    if (WebSocket2.instances[roomId]) {
        const webSocket = WebSocket2.instances[roomId];
        webSocket.receiveFunctions2 = receiveFunctions;
        return webSocket;
    }
    const serviceUrl = window.webSocketUrl || "ws://" + window.location.host + "/websocket";
    WebSocket2.instances[roomId] = new WebSocket2({ serviceUrl, roomId, receiveFunctions });
    setReceiveFunctions(WebSocket2.instances[roomId]);
    return WebSocket2.instances[roomId];
};

const setReceiveFunctions = (webSocket) => {
    webSocket.setReceiveFunction('startShare', (data) => {
        window.receSharingData = data;
        Bridge.receiveStartShare(data);
    });

    webSocket.setReceiveFunction('endShare', (data) => {
        window.receSharingData = null;
        Bridge.receiveEndShare(data);
    });

    webSocket.setReceiveFunction('add', (data) => {
        if (webSocket.id !== data.id) return;
        const { SendSharingData, ReceSharingData, DeviceType } = window.visitUser;
        if (SendSharingData || ReceSharingData || DeviceType !== 1) return;
        webSocket.send('addShare', { id: data.id });
    });

    webSocket.setReceiveFunction('remove', (data) => {
        if (window.receSharingData && window.receSharingData.webSocketId === data.id) {
            window.receSharingData = null;
            Bridge.receiveEndShare(null);
        }
    });

    webSocket.setReceiveFunction('addShare', (data) => {
        if (!window.sendSharingData) return;
        webSocket.send('sendSharingData', { shareData: window.sendSharingData, id: data.id });
    });

    webSocket.setReceiveFunction('sendSharingData', (data) => {
        if (webSocket.id !== data.id) return;
        window.receSharingData = data.shareData;
        Bridge.jsToNative('setReceSharingData', data.shareData);
        window.setReceSharingData && window.setReceSharingData(data.shareData);
    });

    webSocket.setReceiveFunction('receiveService', (data) => {
        if (window.visitUser.DeviceType !== 1) return;
        Bridge.jsToNative('receiveService', data);
    });

    webSocket.setReceiveFunction('resetMeeting', (data) => {
        if (window.visitUser.DeviceType !== 1) return;
        Bridge.jsToNative('resetMeeting', data);
        if (webSocket.receiveFunctions2.refreshMeetingSubjects) {
            webSocket.receiveFunctions2.refreshMeetingSubjects(data);
        }
    });

    webSocket.setReceiveFunction('adjournMeeting', (data) => {
        if (window.visitUser.DeviceType !== 1) return;
        Bridge.jsToNative('adjournMeeting', data);
    });

    webSocket.setReceiveFunction('sendMeetingNotice', (data) => {
        if (window.visitUser.DeviceType !== 1) return;
        Bridge.jsToNative('sendMeetingNotice', data);
    });

    webSocket.setReceiveFunction('closeMeetingNotice', (data) => {
        if (window.visitUser.DeviceType !== 1) return;
        Bridge.jsToNative('closeMeetingNotice', data);
    });

    webSocket.setReceiveFunction('syncBigScreen', (data) => {
        if (window.visitUser.DeviceType !== 1) return;
        Bridge.jsToNative('syncBigScreen', data);
    });

    webSocket.setReceiveFunction('uniteOpen', (data) => {
        if (window.visitUser.DeviceType !== 1 && window.visitUser.DeviceType !== 3) return;
        Bridge.jsToNative('openFile', data);
    });

    webSocket.setReceiveFunction('uniteClose', (data) => {
        if (window.visitUser.DeviceType !== 1 && window.visitUser.DeviceType !== 3) return;
        Bridge.jsToNative('closeFile', data);
    });

    webSocket.setReceiveFunction('sysncFullScreen', (data) => {
        if (window.visitUser.DeviceType !== 1 && window.visitUser.DeviceType !== 3) return;
        Bridge.jsToNative('sysncFullScreen', data);
    });

    webSocket.setReceiveFunction('videoToBack', (data) => {
        if (window.visitUser.DeviceType !== 1 && window.visitUser.DeviceType !== 3) return;
        Bridge.jsToNative('videoToBack', data);
    });

    webSocket.setReceiveFunction('onAsrOfflineResult', (data) => {
        if (window.visitUser.DeviceType !== 1 && window.visitUser.DeviceType !== 3) return;
        Bridge.jsToNative('onAsrOfflineResult', data);
        window.asrConfid = null;
        window.onAsrOfflineResult = null;
    });
};

export default WebSocket2;